package com.boruan.qq.zxgylibrary.ui.activities;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.CircleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.animation.Animation;
import com.amap.api.maps.model.animation.TranslateAnimation;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.core.SuggestionCity;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.boruan.qq.zxgylibrary.R;
import com.boruan.qq.zxgylibrary.R2;
import com.boruan.qq.zxgylibrary.base.BaseOneActivity;
import com.boruan.qq.zxgylibrary.constants.ConstantInfo;
import com.boruan.qq.zxgylibrary.utils.CustomDialog;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.OnClick;

/**
 * Created by 崔琦 on 2019/12/12.
 * des: 拖动地图选择位置以及搜索功能
 */

public class LocationFromMapActivity extends BaseOneActivity implements AMap.OnMarkerClickListener, AMap.OnMapLoadedListener, AMap.OnMapClickListener, LocationSource, AMapLocationListener, GeocodeSearch.OnGeocodeSearchListener, AMap.OnCameraChangeListener, PoiSearch.OnPoiSearchListener {

    @BindView(R2.id.tv_current_city)
    TextView tvCurrentCity;
    @BindView(R2.id.v_line)
    View vLine;
    @BindView(R2.id.edt_search_content)
    EditText edtSearchContent;
    @BindView(R2.id.search_maps_bar)
    RelativeLayout searchMapsBar;
    @BindView(R2.id.dialog_search_recycle)
    RecyclerView dialogSearchRecycle;
    @BindView(R2.id.map_view)
    MapView mapView;

    private AMap mAMap;
    private Marker mGPSMarker; //定位位置显示
    private AMapLocation location;
    private LocationSource.OnLocationChangedListener mListener;
    public static int WRITE_COARSE_LOCATION_REQUEST_CODE = 100;

    //声明AMapLocationClient类对象
    public AMapLocationClient mLocationClient = null;
    //声明mLocationOption对象
    public AMapLocationClientOption mLocationOption = null;
    //你编码对象
    private GeocodeSearch geocoderSearch;

    private String actualAddr;
    private Double actualLon;
    private Double actualLat;
    private String city;
    private MarkerOptions markOptions;
    private LatLng latLng;
    private String addressName;
    /** 拖动地图后的经纬度 */
    private double mLat;
    private double mLon;

    private LatLonPoint searchLatlonPoint;
    private PoiItem firstItem;

    private SearchAdapter searchAdapter;
    private String deepType = "";// poi搜索类型
    private PoiSearch.Query query;// Poi查询条件类
    private PoiSearch poiSearch;
    private List<PoiItem> poiItems;// poi数据
    //当前定位的城市名
    private String mCity;
    private CustomDialog customDialog;

    public static double lat;
    /** 经度 */
    public static double lng;
    @Override
    protected int getLayoutId() {
        return R.layout.drug_activity_location_from_map;
    }

    @Override
    protected void init(Bundle savedInstanceState) {
        mCity = ConstantInfo.mCity;
        tvCurrentCity.setText(mCity);
        poiItems = new ArrayList<>();
        customDialog = new CustomDialog(this, R.style.CustomDialog);
        customDialog.show();
        LinearLayoutManager manager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false);
        dialogSearchRecycle.setLayoutManager(manager);
        searchAdapter = new SearchAdapter();
        dialogSearchRecycle.setAdapter(searchAdapter);

        mapView.onCreate(savedInstanceState);
        geocoderSearch = new GeocodeSearch(this);
        mAMap = mapView.getMap();
        // 设置定位监听
        mAMap.setOnMapLoadedListener(this);
        mAMap.setOnMarkerClickListener(this);
        mAMap.setOnMapClickListener(this);

        mAMap.setLocationSource(this);
        //设置地图拖动监听
        mAMap.setOnCameraChangeListener(this);

        geocoderSearch.setOnGeocodeSearchListener(this);

        MyLocationStyle myLocationStyle = new MyLocationStyle();
        myLocationStyle.strokeWidth(0f);// 设置圆形的边框粗细
        myLocationStyle.anchor(0.5f, 0.7f);
        mAMap.setMyLocationStyle(myLocationStyle);

        mAMap.moveCamera(CameraUpdateFactory.zoomTo(16)); //缩放比例

        //添加一个圆
        CircleOptions circleOptions = new CircleOptions();
        circleOptions.radius(20.0f);
        mAMap.addCircle(circleOptions);

        //设置amap的属性
        UiSettings settings = mAMap.getUiSettings();
        settings.setMyLocationButtonEnabled(true);// 设置默认定位按钮是否显示
        mAMap.setMyLocationEnabled(true);// 设置为true表示显示定位层并可触发定位，false表示隐藏定位层并不可触发定位，默认是false

        /**
         * 输入监听
         * */
        edtSearchContent.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                textChangeSearch(charSequence);
            }

            @Override
            public void afterTextChanged(Editable editable) {

            }
        });
    }

    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        location = aMapLocation;
        if (mListener != null && location != null) {
            if (location != null && location.getErrorCode() == 0) {
                mListener.onLocationChanged(location);// 显示系统箭头
                lat = location.getLatitude();
                lng = location.getLongitude();
                LatLng curLatLng = new LatLng(location.getLatitude(), location.getLongitude());
                searchLatlonPoint = new LatLonPoint(curLatLng.latitude, curLatLng.longitude);
                doSearchQuery();
                city = location.getCity();
                /** 拖动地图选取位置，先改成点击地图上的点修改位置 */
                this.actualAddr = location.getAddress();
                this.actualLon = location.getLongitude();
                this.actualLat = location.getLatitude();
                mLocationClient.stopLocation();
            }
        }
        else {
            Toast.makeText(this, "定位失败", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onCameraChange(CameraPosition cameraPosition) {

    }

    @Override
    public void onCameraChangeFinish(CameraPosition cameraPosition) {
        mLat = cameraPosition.target.latitude;
        mLon = cameraPosition.target.longitude;
        searchLatlonPoint = new LatLonPoint(mLat,mLon);

        Log.i("经纬度",mLat + "---" + mLon);
        getAddressByLatlng(cameraPosition.target);
        startJumpAnimation();
    }

    /**
     * 逆地理获取准确位置
     * */
    private void getAddressByLatlng(LatLng latLng) {
        //逆地理编码查询条件：逆地理编码查询的地理坐标点、查询范围、坐标类型。
        double lat = (double)(Math.round(latLng.latitude*1000000)/1000000.0);
        double lon = (double)(Math.round(latLng.longitude*1000000)/1000000.0);
        LatLonPoint latLonPoint = new LatLonPoint(lat, lon);
        RegeocodeQuery query = new RegeocodeQuery(latLonPoint, -5f, GeocodeSearch.AMAP);

        //异步查询
        geocoderSearch.getFromLocationAsyn(query);
    }

    @Override
    public void onRegeocodeSearched(RegeocodeResult result, int rCode) {
        if (rCode == AMapException.CODE_AMAP_SUCCESS) {
            if (result != null && result.getRegeocodeAddress() != null
                    && result.getRegeocodeAddress().getFormatAddress() != null) {
                String address = result.getRegeocodeAddress().getProvince() + result.getRegeocodeAddress().getCity() + result.getRegeocodeAddress().getDistrict() + result.getRegeocodeAddress().getTownship();
                firstItem = new PoiItem("regeo", searchLatlonPoint, address, address);
                doSearchQuery();
            }
        } else {
            Toast.makeText(LocationFromMapActivity.this, "error code is " + rCode, Toast.LENGTH_SHORT).show();
        }
    }

    private boolean isFirstAnimation = false;
    private void textChangeSearch(CharSequence charSequence) {
        if (!isFirstAnimation){
            mapView.setVisibility(View.GONE);
            android.view.animation.Animation animation = AnimationUtils.loadAnimation(this, R.anim.drug_slide_in_bottom);
            dialogSearchRecycle.startAnimation(animation);
            isFirstAnimation = true;
        }
        String content = charSequence.toString().trim();//获取自动提示输入框的内容
        int currentPage = 0;
        query = new PoiSearch.Query(content, deepType, mCity);// 第一个参数表示搜索字符串，第二个参数表示poi搜索类型，第三个参数表示poi搜索区域（空字符串代表全国）
        query.setPageSize(20);// 设置每页最多返回多少条poiitem
        query.setPageNum(currentPage);// 设置查第一页

        poiSearch = new PoiSearch(this, query);
        poiSearch.setOnPoiSearchListener(this);
        poiSearch.searchPOIAsyn();// 异步搜索
    }

    /**
     * 开始进行poi搜索
     */
    protected void doSearchQuery() {
        int currentPage = 0;
        query = new PoiSearch.Query("", deepType, mCity);// 第一个参数表示搜索字符串，第二个参数表示poi搜索类型，第三个参数表示poi搜索区域（空字符串代表全国）
        query.setCityLimit(true);
        query.setPageSize(20);
        query.setPageNum(currentPage);

        if (searchLatlonPoint != null) {
            poiSearch = new PoiSearch(this, query);
            poiSearch.setOnPoiSearchListener(this);
            poiSearch.setBound(new PoiSearch.SearchBound(searchLatlonPoint, 1000, true));//
            poiSearch.searchPOIAsyn();
        }
    }

    @Override
    public void onMapClick(LatLng latLng) {

    }

    @Override
    public void onMapLoaded() {
        Log.i("MMM","被调用了吗");
        addMarkerInScreenCenter(null);
    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        if (marker.isInfoWindowShown()) {
            marker.hideInfoWindow();
        }
        else {
            marker.showInfoWindow();
        }
        return false;
    }

    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        mListener = onLocationChangedListener;
        //初始化定位
        mLocationClient = new AMapLocationClient(getApplicationContext());
        //设置定位回调监听
        mLocationClient.setLocationListener(this);

        //初始化定位参数
        mLocationOption = new AMapLocationClientOption();
        //设置定位模式为高精度模式，Battery_Saving为低功耗模式，Device_Sensors是仅设备模式
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        //设置是否返回地址信息（默认返回地址信息）
        mLocationOption.setNeedAddress(true);
        //设置是否只定位一次,默认为false
        mLocationOption.setOnceLocation(false);
        //设置是否强制刷新WIFI，默认为强制刷新
        mLocationOption.setWifiActiveScan(true);
        //设置是否允许模拟位置,默认为false，不允许模拟位置
        mLocationOption.setMockEnable(false);
        //设置定位间隔,单位毫秒,默认为2000ms
        mLocationOption.setInterval(2000 * 10);
        //给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(mLocationOption);
        //启动定位
        mLocationClient.startLocation();
    }

    @Override
    public void deactivate() {
        mListener = null;
        if (mLocationClient != null)
        {
            mLocationClient.stopLocation();
            mLocationClient.onDestroy();
        }
    }

    private void addMarkerInScreenCenter(LatLng locationLatLng) {
        LatLng latLng = mAMap.getCameraPosition().target;
        Point screenPosition = mAMap.getProjection().toScreenLocation(latLng);
        mGPSMarker = mAMap.addMarker(new MarkerOptions()
                .anchor(0.5f,0.5f)
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.drug_purple_pin)));
        //设置Marker在屏幕上,不跟随地图移动
        mGPSMarker.setPositionByPixels(screenPosition.x,screenPosition.y);
        mGPSMarker.setZIndex(1);
    }

    /**
     * 屏幕中心marker 跳动
     */
    public void startJumpAnimation() {

        if (mGPSMarker != null ) {
            //根据屏幕距离计算需要移动的目标点
            final LatLng latLng = mGPSMarker.getPosition();
            Point point =  mAMap.getProjection().toScreenLocation(latLng);
            point.y -= dip2px(this,125);
            LatLng target = mAMap.getProjection()
                    .fromScreenLocation(point);
            //使用TranslateAnimation,填写一个需要移动的目标点
            Animation animation = new TranslateAnimation(target);
            animation.setInterpolator(new Interpolator() {
                @Override
                public float getInterpolation(float input) {
                    // 模拟重加速度的interpolator
                    if(input <= 0.5) {
                        return (float) (0.5f - 2 * (0.5 - input) * (0.5 - input));
                    } else {
                        return (float) (0.5f - Math.sqrt((input - 0.5f)*(1.5f - input)));
                    }
                }
            });
            //整个移动所需要的时间
            animation.setDuration(600);
            //设置动画
            mGPSMarker.setAnimation(animation);
            //开始动画
            mGPSMarker.startAnimation();

        } else {
            Log.e("ama","screenMarker is null");
        }
    }

    //dip和px转换
    private static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

    protected void onDestroy() {
        super.onDestroy();
        mapView = null;
        // 销毁定位
        if (mLocationClient != null)
        {
            mLocationClient.stopLocation();
            mLocationClient.onDestroy();
        }
    }

    @Override
    public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {

    }

    @Override
    public void onPoiSearched(PoiResult poiResult, int resultCode) {
        if (resultCode == AMapException.CODE_AMAP_SUCCESS) {
            if (poiResult != null && poiResult.getQuery() != null) {
                if (poiResult.getQuery().equals(query)) {
                    poiItems = poiResult.getPois();// 取得第一页的poiitem数据，页数从数字0开始
                    Log.i("Items", poiItems.size() + "");
                    List<SuggestionCity> suggestionCities = poiResult.getSearchSuggestionCitys();
                    if (poiItems != null && poiItems.size() > 0) {
                        searchAdapter.setData(poiItems);
                    } else {
                        //Toast.makeText(LocationFromMapActivity.this, "无搜索结果", Toast.LENGTH_SHORT).show();
                    }
                }
            } else {
                //Toast.makeText(LocationFromMapActivity.this, "无搜索结果了", Toast.LENGTH_SHORT).show();
            }
        }
        if (customDialog != null){
            customDialog.dismiss();
        }
    }

    @Override
    public void onPoiItemSearched(PoiItem poiItem, int i) {

    }

    @OnClick(R2.id.back)
    public void onViewClicked() {
        finish();
    }

    /**
     * poi适配器
     */
    private class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.SearchViewHolder> {
        private List<PoiItem> mData;

        public void setData(List<PoiItem> mData) {
            this.mData = mData;
            notifyDataSetChanged();
        }

        @NonNull
        @Override
        public SearchAdapter.SearchViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            View view = inflater.inflate(R.layout.drug_item_search, parent, false);
            return new SearchAdapter.SearchViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull SearchAdapter.SearchViewHolder holder, final int position) {
            holder.tvCityName.setText(mData.get(position).getTitle());
            holder.tvCityContent.setText(mData.get(position).getSnippet());
            holder.tvLocation.setText(fromMeter2KM(gps2m(mData.get(position).getLatLonPoint().getLatitude(), mData.get(position).getLatLonPoint().getLongitude(), lat, lng)));
            holder.llSearchMain.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    hideKeyboard();
                    Intent intent = new Intent();
                    intent.putExtra("address", mData.get(position).getTitle());
                    intent.putExtra("lat", mData.get(position).getLatLonPoint().getLatitude());
                    Log.i("test", mData.get(position).getLatLonPoint().getLatitude() + "");
                    intent.putExtra("lon", mData.get(position).getLatLonPoint().getLongitude());
					intent.putExtra("province",mData.get(position).getProvinceName());
                    intent.putExtra("city",mData.get(position).getCityName());
                    intent.putExtra("area",mData.get(position).getAdName());
                    intent.putExtra("adCode",mData.get(position).getAdCode());
                    setResult(22, intent);
                    finish();
                }
            });
        }

        @Override
        public int getItemCount() {
            return mData == null ? 0 : mData.size();
        }

        public class SearchViewHolder extends RecyclerView.ViewHolder {
            LinearLayout llSearchMain;
            TextView tvCityName;
            TextView tvCityContent;
            TextView tvLocation;

            public SearchViewHolder(View itemView) {
                super(itemView);
                llSearchMain = (LinearLayout) itemView.findViewById(R.id.ll_search_main);
                tvCityName = (TextView) itemView.findViewById(R.id.tv_city_name);
                tvCityContent = (TextView) itemView.findViewById(R.id.tv_city_content);
                tvLocation = (TextView) itemView.findViewById(R.id.tv_location);
            }
        }
    }

    public void hideKeyboard() {
        View view = LocationFromMapActivity.this.getCurrentFocus();
        if (view != null) {
            InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    /**
     * 地球半径
     */
    private int EARTH_RADIUS = 6371000;

    private double gps2m(double lat_a, double lng_a, double lat_b, double lng_b) {
        double radLat1 = (lat_a * Math.PI / 180.0);
        double radLat2 = (lat_b * Math.PI / 180.0);
        double a = radLat1 - radLat2;
        double b = (lng_a - lng_b) * Math.PI / 180.0;
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000) / 10000;
        return s;
    }

    /**
     * 将m装换成km
     */
    public static String fromMeter2KM(double meters) {
        meters = Math.round(meters / 100d) / 10d;
        String s = String.valueOf(meters);
        if (s.equals("0.0")) {
            s = "0";
        }
        s += "km";
        return s;
    }
}
